package com.fourcitizens.playas.scrapper;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.File;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

public class Scrapper {
	public static final String BASE_URL = "http://www.mma.es/portal/secciones/acm/aguas_marinas_litoral/guia_playas/";
	public static final String MMA_URL = "http://www.mma.es";

	private static final String SOURCE_DIR = "source_data" + File.separator;
	private static final String PROVINCES_DIR = SOURCE_DIR + "provinces" + File.separator;
	private static final String PROVINCES_FILE_NAME = SOURCE_DIR + "provincias";

	private static final String IMAGES_DIR = SOURCE_DIR + "images" + File.separator;
	private static final String CSV_FILE_NAME = SOURCE_DIR + "playas.csv";
	
	private Scrapper() {
	}

	private static void makeDirectory (String directoryname) {
		File dir = new File(directoryname);
		if (!dir.exists()) {
			dir.mkdirs();
		}
	}

	private static void init() {
		makeDirectory(PROVINCES_DIR);
		makeDirectory(IMAGES_DIR);
		File csvFile = new File(CSV_FILE_NAME);
		if (csvFile.exists())
			csvFile.delete();
	}

	public static void downloadAndParseToXml(String url, String filenameWithoutExtension) throws MalformedURLException, IOException {
		HttpFileDownloader.saveUrl(filenameWithoutExtension + ".html", url);
		Html2XmlConverter.html2xml(filenameWithoutExtension + ".html", filenameWithoutExtension + ".xml");
	}

	public static void downloadViaHttpAndParseToXml(String url, String filenameWithoutExtension) {
		HttpCommunicator.saveHttpContent(filenameWithoutExtension + ".html", url);
		Html2XmlConverter.html2xml(filenameWithoutExtension + ".html", filenameWithoutExtension + ".xml");
	}

	private static final boolean DEBUG = false;
	private static final String DEBUG_PROVINCE_STRING = "asturias";
	private static final String DEBUG_TOWN_STRING = "cudillero";
	private static final String DEBUG_BEACH_STRING = "Playa El Riego";

	public static void main(String[] args) {
		long startTime = System.currentTimeMillis();
		try {
			init();
			FileOutputStream csvFile = new FileOutputStream(CSV_FILE_NAME);

			downloadAndParseToXml(BASE_URL, PROVINCES_FILE_NAME);
			List<Province> provinces = XmlParser.parseProvinces(PROVINCES_FILE_NAME + ".xml");

			for (Province province : provinces) {
				if (DEBUG && !province.getName().toLowerCase().equals(DEBUG_PROVINCE_STRING.toLowerCase()))
					continue;

				System.out.println("--");
				System.out.println(province);
				System.out.println("--");

				downloadAndParseToXml(province.getUrl(), PROVINCES_DIR + province.getName());
				List<Town> towns =XmlParser.parseTowns(PROVINCES_DIR + province.getName() + ".xml", province);
				makeDirectory(PROVINCES_DIR + province.getName());
				for (Town town : towns) {
					if (DEBUG && !town.getName().toLowerCase().equals(DEBUG_TOWN_STRING.toLowerCase()))
						continue;

					System.out.println(town);
					downloadAndParseToXml(town.getUrl(), PROVINCES_DIR + province.getName() + File.separator + town.getName());
					List<Beach> beaches = XmlParser.parseBeaches(PROVINCES_DIR + province.getName() + File.separator + town.getName() + ".xml" , town);
					makeDirectory(PROVINCES_DIR + province.getName() + File.separator + town.getName());
					for (Beach beach : beaches) {
						if (DEBUG && !beach.getName().toLowerCase().equals(DEBUG_BEACH_STRING.toLowerCase()))
							continue;
						
						try {
							System.out.println(beach);
							downloadViaHttpAndParseToXml(beach.getUrl(), PROVINCES_DIR + province.getName() + File.separator + town.getName() + File.separator + beach.getName());
							PrintableBeach pBeach = XmlParser.parseBeachDetail(PROVINCES_DIR + province.getName() + File.separator + town.getName() + File.separator + beach.getName() + ".xml", IMAGES_DIR, town);
							
							StringBuffer sb = new StringBuffer();
							sb.append("http://maps.google.com/maps/api/geocode/json?address=Playa+");
							sb.append(pBeach.getName().replace(' ', '+'));
							sb.append(',');
							sb.append(pBeach.getTown().replace(' ', '+'));
							sb.append(',');
							sb.append(pBeach.getProvince().replace(' ', '+'));
							sb.append(',');
							sb.append(pBeach.getCountry().replace(' ', '+'));
							sb.append("&sensor=false");

							String json = HttpCommunicator.getHttpContent(sb.toString());
							if (json != null) {
								String latitude = getLatitude(json);
								if (latitude != null)
									pBeach.setLaitude(latitude);
								String longitude = getLongitude(json);
								if (longitude != null)
									pBeach.setLongitude(longitude);
							}
							
							System.out.println(pBeach.toCSVRow());
							csvFile.write(pBeach.toCSVRow().getBytes(Charset.forName("ISO-8859-1")));
							// csvFile.write(pBeach.toCSVRow().getBytes(Charset.forName("UTF-8")));
						}
						catch (Exception e) {
							System.err.println("!!!!!ERROR AL PROCESAR PLAYA ==>  " + beach.getName());
							if (DEBUG)
								throw e;
						}
					}
					System.out.print('\n');
				}
				System.out.println("\n\n");	
			}
			csvFile.close();
		}
		catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		long elapsed = System.currentTimeMillis() - startTime;
		DateFormat df = new SimpleDateFormat("HH 'hours', mm 'mins,' ss 'seconds'");
		df.setTimeZone(TimeZone.getTimeZone("GMT+0"));
		System.out.println("Execution time: " + df.format(new Date(elapsed)));
	}
	
	private static String getLatitude(String json) {
		try {
			return json.substring(json.indexOf("\"lat\":") + 7, json.indexOf(',', json.indexOf("\"lat\":")));
		}
		catch (StringIndexOutOfBoundsException e) {
			return null;
		}
	}
	
	private static String getLongitude(String json) {
		try {
			return json.substring(json.indexOf("\"lng\":") + 7, json.indexOf('\n', json.indexOf("\"lng\":")));
		}
		catch (StringIndexOutOfBoundsException e) {
			return null;
		}
	}
}
